home *** CD-ROM | disk | FTP | other *** search
-
- Using Modeless Dialogs as MDI Child Windows
- -------------------------------------------
-
- This file contains important information for using the TPW MDITypes
- unit. You should read this before using the unit. As of this writing
- (11/30/91 at 3:43 PM), the code works well. There were problems with
- sporadic UAEs in my previeous testing, but these seem to have been
- resolved. The upshot of the exercise has been to follow these rules:
-
- 1. *NEVER* change the style bits of an MDI child window after it has
- been created. This makes Windows unstable.
-
- 2. *NEVER* delete menu items from the system menu of the MDI child
- window. You can disable menu items, but deleting them seems to
- lead to further Windows instability.
-
- 3. If you want to prevent a windoe from changing size, handle
- wm_SysCommand and check for Msg.wParam = sc_Size, sc_Maximize,
- and/or wm_Minimize. Return 1 in Msg.Result if you see these values,
- otherwise call DefWndProc(Msg).
-
- The program now seems steady as a rock. The MDI child windows
- containing dialog boxes don't look exactly like I wanted them to look,
- but the program doesn't crater Windows any more. I'm willing to live
- with the aesthetics for now.
-
- The archive file contains the following files:
-
- MDIEXAM ACL 237 Test program accelerators
- MDIDLG1 DLG 1185 Test program MDI child dialog #1
- MDIDLG2 DLG 578 Test program MDI child dialog #2
- DIALOG1 ICO 1846 Icon for MDI child dialog #1 windows
- DIALOG2 ICO 1846 Icon for MDI child dialog #2 windows
- MDIEDIT ICO 1846 Icon for MDI child edit windoww
- MDIEXAM ICO 1846 Icon for MDI test program
- MDIEXAM INC 735 Include file for the test program
- MDIEDIT MNU 802 Dialog & edit child windows menu
- MDIEXAM MNU 502 Frame menu for case of no children
- MDIRECT MNU 535 Random rectangle child windows menu
- MDIEXAM PAS 44832 Test program source code
- MDITYPES PAS 27672 MDI child window unit source code
- MDIEXAM RC 328 Test program RC file. For use with RW or WRT!
-
- The MDITypes unit is the heart of the implementation. There are three
- different object types defined in the unit, as follows:
-
- TMDIChild: TMDIChild descends from TWindow. The type supports
- changing the current menu displayed by the frame window
- when an MDI child window is activated or deactivated. To
- accomplish this end, the type defines a response method for
- the wm_MDIActivate message.
-
- TMDIDialog: This type descends from TMDIChild. It supports the concept
- of a modeless dialog as an MDI child window.
-
- TMDIFrame: This type is a descendant of TMDIWindow. It defines three
- methods that were not included TMDIWindow. These allow you
- to find the OWL object associated with an MDI child window
- handle (GetChild(TheWnd: HWnd)); closing a specific child
- window (TMDIWindow only supports closing all child windows;
- to destroy a single window, you have to double click on the
- child's system menu); and a wm_InitMenu reponse method to
- simplify the process of allowing an MDI child window to
- modify the state of the current menu. This is useful for
- those cases where you have an Edit menu, for example, and
- you need to gray items on it based on whether or not you
- can undo an edit, paste, cut, etc.
-
- The source code is heavily commented, so you should be able to follow
- all that is going on in it. Any questions should be directed to me,
- Tony Vitabile 76054, 1450 on BPROGA section 8.
-
-
- USING MULTIPLE MENUS IN AN MDI PROGRAM
- --------------------------------------
-
- Being able to have a different menu be displayed when a particular type
- of MDI child window is currently active is a major feature of the MDI
- specification. However, OWL doesn't provide any support for this
- feature. This isn't a difficult feature to support, but it would be
- easier if there were an object type that encapsulated all the work
- involved for you. Now there is such an object type: TMDIChild. Here's
- how you use it.
-
- Define an object type in your program that descends from TMDIChild.
- This allows you to add other functionality your window may need in
- addition to that provided by TMDIChild. In your Init constructor, you
- provide two additional pieces of information that the TMDIChild window
- will need to support switching the frame menu. These are:
-
- - A handle to the menu to be displayed when this window is active;
- - The position number of the Window popup menu item on the menu.
-
- TMDIChild stores this information in two fields, then determines the
- menu handle of the Window popup menu and saves that as well. That's all
- you have to do. From here on, changing the menu is automatically
- handled by TMDIChild's methods.
-
- When a TMDIChild receives a wm_MDIActivate message, the wParam field
- tells the window whether it's being activated or deactivated. TMDIChild
- uses this information to determine whether it should switch to the frame
- window's default menu (the one included in the frame window's Init
- constructor) or the one whose handle is contained in this instance of
- TMDIChild. The wm_MDIActivate response method retrieves the appropriate
- handles from the appropriate objects, then sends the wm_MDIChangeMenu
- message to the MDI Client window. After that, the job is done.
-
- Note that Load & Store methods are provided for TMDIChild so that you
- can save descendants and instances of this type on streams. See the
- section at the end of this README.TXT file for more information
- regarding the proper streaming of TMDIChild & its descendants.
-
-
-
- USING A MODELESS DIALOG AS AN MDI CHILD WINDOW
- ----------------------------------------------
-
- So you want to use a modeless dialog box as an MDI child window? Well,
- it's not quite as easy as it might seem, nor is it as difficult as you
- may think. The MDITypes unit was written to provide a basis for
- supporting this type of feature in your programs. All the work involved
- in maintaining a window of this type is encapsulated in the type
- TMDIDialog. The paragraphs that follow describe how you extend this
- type to include your dialog box.
-
- TMDIDialog is an abstract type. A window of type TMDIDialog itself
- should never exist. This is because TMDIDialog is a generic type and
- does not have a predefined dialog template that it uses. YOUR code
- supplies that template. After you make the dialog known, TMDIDialog's
- methods then do all the work.
-
- TMDIDialog defines a new method called InitDialog. This is a function
- that returns a pointer to an object of type TDlgWindow. To create your
- own MDI dialog box type, you descend from TMDIDialog and then override
- InitDialog. InitDialog should call New, passing the constructor of
- an object descended from type TDlgWindow. The value returned by New is
- the value you return to InitDialog's caller. For example:
-
- type
- MyDialog = object (TDlgWindow)
- .
- .
- .
- end;
- MyMDIDialog = object (TMDIDialog)
- .
- .
- .
- function InitDialog: PDlgWindow;
- virtual;
- .
- .
- .
- end;
- .
- .
- .
- function MyMDIDialog.InitDialog: PDlgWindow;
- begin { MyMDIDialog.InitDialog }
- InitDialog := PDlgWindow(New(PMyDialog, Init(...)))
- end { MyMDIDialog.InitDialog };
-
- That's it! From here on, TMDIDialog takes care of all the details.
-
- Of course, if you want your MDI dialog type to do more, you'll have to
- add methods to cover those situations.
-
- The sample program included in this archive, MDIEXAM.PAS, shows how to
- create 2 different types of MDI dialog child windows.
-
-
- STREAMING TMDICHILD DESCENDANTS
- -------------------------------
-
- The Load & Store methods for both TMDIChild & TMDIDialog take pretty
- simplistic approaches to reading & writing windows of these types on
- streams. They assume the value written to the stream for a menu handle
- will be valid when the window is read. This is *NOT* true, but there is
- nothing that TMDIChild or TMDIDialog can do about about it, since they
- have no way of knowing the resource name associated with that menu.
-
- If you intend to stream your TMDIChild and/or TMDIDialog descendants,
- you should put some code in your descendant's Load/Store method to make
- sure that the menu handles in your windows are correct. For example:
-
- constructor MyMDIChild.Load(var S: TStream);
- begin { MyMDIChild.Load }
- { Get the window from the stream }
- TMDIChild.Load(S);
- { Now fix up the menus }
- Menu := LoadMenu(HInstance, mymenu); { or use a global var }
- WndMenu := GetSubMenu(Menu, MenuPos) { Set windo menu properly}
- end { MyMDIChild.Load };
-
- This will properly initialize the menu handles for the MDI child window.
- It is important that you set WndMenu too! Failure to do so will have
- unpredictable results, and may crash Windows.
-
- If your window is a descendant of MDIDialog, you will need to implement
- code like that above. Make sure you call TMDIDialog.Load instead of
- TMDIChild.Load. TMDIDialog.Load calls TMDIChild.Load and performs
- additional steps required for the type.
-
-
- COPYRIGHT
- ---------
-
- The program and unit source code included in this archive are Copyright
- (c) 1991 by Anthony M. Vitabile. All rights are reserved. Permission
- is hereby granted to all who desire to use this source code in their
- programs provided the above copyright is included in the program.
-